<template>
  <div class="three-editor">
    <!-- 顶部导航栏 -->
    <header class="editor-header">
      <div class="logo">Three.js Editor</div>
      <div class="menu">
        <button @click="newScene" class="menu-btn">
          <i class="fas fa-file"></i> 新建
        </button>
        <button @click="saveScene" class="menu-btn">
          <i class="fas fa-save"></i> 保存
        </button>
        <button @click="loadScene" class="menu-btn">
          <i class="fas fa-upload"></i> 加载
        </button>
        <button @click="exportScene" class="menu-btn">
          <i class="fas fa-download"></i> 导出
        </button>
        <label class="import-btn menu-btn">
          <i class="fas fa-file-import"></i> 导入模型
          <input
            type="file"
            ref="fileInput"
            @change="handleFileImport"
            accept=".glb,.gltf,.obj,.fbx,.stl,.dae"
            hidden
          />
        </label>
      </div>
    </header>

    <div class="editor-container">
      <!-- 左侧工具栏 -->
      <aside class="toolbar">
        <h3>添加对象</h3>
        <div class="tool-group">
          <button @click="addObject('box')" class="tool-btn">
            <i class="fas fa-cube"></i> 立方体
          </button>
          <button @click="addObject('sphere')" class="tool-btn">
            <i class="fas fa-circle"></i> 球体
          </button>
          <button @click="addObject('cylinder')" class="tool-btn">
            <i class="fas fa-cylinder"></i> 圆柱体
          </button>
          <button @click="addObject('plane')" class="tool-btn">
            <i class="fas fa-square"></i> 平面
          </button>
          <button @click="addObject('light')" class="tool-btn">
            <i class="fas fa-lightbulb"></i> 点光源
          </button>
          <button @click="addObject('camera')" class="tool-btn">
            <i class="fas fa-camera"></i> 相机
          </button>
        </div>

        <h3>材质</h3>
        <div class="tool-group">
          <button @click="changeMaterial('basic')" class="tool-btn">
            基础材质
          </button>
          <button @click="changeMaterial('lambert')" class="tool-btn">
            兰伯特材质
          </button>
          <button @click="changeMaterial('phong')" class="tool-btn">
            冯氏材质
          </button>
          <button @click="changeMaterial('standard')" class="tool-btn">
            标准材质
          </button>
        </div>

        <h3>颜色</h3>
        <div class="color-picker">
          <input type="color" v-model="selectedColor" @change="changeColor" />
        </div>

        <h3>变换模式</h3>
        <div class="tool-group">
          <button @click="setTransformMode('translate')" class="tool-btn">
            <i class="fas fa-arrows"></i> 移动
          </button>
          <button @click="setTransformMode('rotate')" class="tool-btn">
            <i class="fas fa-sync"></i> 旋转
          </button>
          <button @click="setTransformMode('scale')" class="tool-btn">
            <i class="fas fa-expand"></i> 缩放
          </button>
        </div>
      </aside>

      <!-- 主编辑区域 -->
      <main class="editor-main">
        <div ref="canvasContainer" class="canvas-container"></div>
        <div class="stats">
          <div v-if="selectedObject">
            <h4>选中对象: {{ selectedObject.name }}</h4>
            <div class="object-controls">
              <div class="control-group">
                <label
                  >位置 X:
                  <input
                    type="number"
                    step="0.1"
                    v-model.number="position.x"
                    @input="updatePosition"
                /></label>
                <label
                  >位置 Y:
                  <input
                    type="number"
                    step="0.1"
                    v-model.number="position.y"
                    @input="updatePosition"
                /></label>
                <label
                  >位置 Z:
                  <input
                    type="number"
                    step="0.1"
                    v-model.number="position.z"
                    @input="updatePosition"
                /></label>
              </div>
              <div class="control-group">
                <label
                  >旋转 X:
                  <input
                    type="number"
                    step="0.1"
                    v-model.number="rotation.x"
                    @input="updateRotation"
                /></label>
                <label
                  >旋转 Y:
                  <input
                    type="number"
                    step="0.1"
                    v-model.number="rotation.y"
                    @input="updateRotation"
                /></label>
                <label
                  >旋转 Z:
                  <input
                    type="number"
                    step="0.1"
                    v-model.number="rotation.z"
                    @input="updateRotation"
                /></label>
              </div>
              <div class="control-group">
                <label
                  >缩放 X:
                  <input
                    type="number"
                    step="0.1"
                    v-model.number="scale.x"
                    @input="updateScale"
                /></label>
                <label
                  >缩放 Y:
                  <input
                    type="number"
                    step="0.1"
                    v-model.number="scale.y"
                    @input="updateScale"
                /></label>
                <label
                  >缩放 Z:
                  <input
                    type="number"
                    step="0.1"
                    v-model.number="scale.z"
                    @input="updateScale"
                /></label>
              </div>
              <button @click="deleteObject" class="delete-btn">
                删除选中对象
              </button>
            </div>
          </div>
          <div v-else>
            <h4>未选中任何对象</h4>
            <p>点击场景中的对象进行选择</p>
          </div>
        </div>
      </main>
      <!-- 右侧对象列表 -->
      <aside class="object-list">
        <h3>场景对象</h3>
        <ul>
          <li
            @click="selectSceneObject(scene)"
            :class="{ selected: selectedObject === scene }"
          >
            <i class="fas fa-globe"></i> 场景
          </li>
          <template v-for="child in scene.children">
            <li
              :key="child.uuid"
              @click="selectSceneObject(child)"
              :class="{ selected: selectedObject === child }"
            >
              <i class="fas" :class="getObjectIcon(child)"></i>
              {{ child.name || child.type }}
            </li>
          </template>
        </ul>
      </aside>
    </div>
    <!-- 导入进度提示 -->
    <div v-if="importing" class="import-progress">
      <div class="progress-content">
        <div class="spinner"></div>
        <p>正在导入: {{ importProgress }}%</p>
        <p>{{ importFileName }}</p>
      </div>
    </div>
  </div>
</template>

<script>
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import { TransformControls } from 'three/examples/jsm/controls/TransformControls'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader'
import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader'
import { STLLoader } from 'three/examples/jsm/loaders/STLLoader'
import { ColladaLoader } from 'three/examples/jsm/loaders/ColladaLoader'
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader'

export default {
  name: 'ThreeEditor',
  data() {
    return {
      // Three.js核心对象
      scene: null,
      camera: null,
      renderer: null,
      controls: null,
      transformControls: null,
      raycaster: null,
      mouse: null,

      // 加载器
      loaders: {},

      // 场景元素
      ambientLight: null,
      directionalLight: null,

      // 状态管理
      selectedObject: null,
      selectedColor: '#ff0000',
      importing: false,
      importProgress: 0,
      importFileName: '',

      // 对象属性
      position: { x: 0, y: 0, z: 0 },
      rotation: { x: 0, y: 0, z: 0 },
      scale: { x: 1, y: 1, z: 1 },

      // 动画循环
      animationId: null
    }
  },
  mounted() {
    this.initLoaders()
    this.initThree()
    this.setupEventListeners()
    this.animate()
  },
  beforeDestroy() {
    // 清理资源
    if (this.animationId) {
      cancelAnimationFrame(this.animationId)
    }

    if (this.renderer) {
      this.renderer.dispose()
    }

    window.removeEventListener('resize', this.onWindowResize)
    window.removeEventListener('click', this.onClick)
    window.removeEventListener('keydown', this.onKeyDown)
  },
  methods: {
    // 初始化各种加载器
    initLoaders() {
      // 初始化DRACO加载器（用于压缩的glTF文件）
      const dracoLoader = new DRACOLoader()
      dracoLoader.setDecoderPath('https://www.gstatic.com/draco/v1/decoders/')

      // GLTF/GLB加载器
      this.loaders.gltf = new GLTFLoader()
      this.loaders.gltf.setDRACOLoader(dracoLoader)

      // OBJ加载器
      this.loaders.obj = new OBJLoader()

      // FBX加载器
      this.loaders.fbx = new FBXLoader()

      // STL加载器
      this.loaders.stl = new STLLoader()

      // Collada加载器
      this.loaders.dae = new ColladaLoader()

      // 为所有加载器设置进度回调
      const self = this
      Object.values(this.loaders).forEach((loader) => {
        if (loader.setProgressCallback) {
          loader.setProgressCallback(function (url, loaded, total) {
            self.importProgress = Math.round((loaded / total) * 100)
          })
        }
      })
    },

    // 初始化Three.js场景
    initThree() {
      // 创建场景
      this.scene = new THREE.Scene()
      this.scene.name = '场景'
      this.scene.background = new THREE.Color(0xf0f0f0)

      // 创建相机
      this.camera = new THREE.PerspectiveCamera(
        75,
        this.$refs.canvasContainer.clientWidth /
          this.$refs.canvasContainer.clientHeight,
        0.1,
        1000
      )
      this.camera.name = '主相机'
      this.camera.position.z = 10

      // 创建渲染器
      this.renderer = new THREE.WebGLRenderer({ antialias: true })
      this.renderer.setSize(
        this.$refs.canvasContainer.clientWidth,
        this.$refs.canvasContainer.clientHeight
      )
      this.$refs.canvasContainer.appendChild(this.renderer.domElement)

      // 添加光源
      this.ambientLight = new THREE.AmbientLight(0xffffff, 0.5)
      this.ambientLight.name = '环境光'
      this.scene.add(this.ambientLight)

      this.directionalLight = new THREE.DirectionalLight(0xffffff, 0.8)
      this.directionalLight.name = '平行光'
      this.directionalLight.position.set(5, 5, 5)
      this.scene.add(this.directionalLight)

      // 添加辅助网格
      const gridHelper = new THREE.GridHelper(20, 20, 0xcccccc, 0xeeeeee)
      gridHelper.name = '网格辅助线'
      this.scene.add(gridHelper)

      // 轨道控制器
      this.controls = new OrbitControls(this.camera, this.renderer.domElement)
      this.controls.enableDamping = true

      // 变换控制器
      this.transformControls = new TransformControls(
        this.camera,
        this.renderer.domElement
      )
      this.transformControls.addEventListener('change', () =>
        this.renderer.render(this.scene, this.camera)
      )
      this.transformControls.addEventListener(
        'dragging-changed',
        function (event) {
          this.controls.enabled = !event.value
        }.bind(this)
      )
      this.scene.add(this.transformControls)

      // 射线投射器（用于物体选择）
      this.raycaster = new THREE.Raycaster()
      this.mouse = new THREE.Vector2()
    },

    // 设置事件监听器
    setupEventListeners() {
      window.addEventListener('resize', this.onWindowResize.bind(this))
      window.addEventListener('click', this.onClick.bind(this))
      window.addEventListener('keydown', this.onKeyDown.bind(this))
    },

    // 窗口大小改变时调整渲染器
    onWindowResize() {
      this.camera.aspect =
        this.$refs.canvasContainer.clientWidth /
        this.$refs.canvasContainer.clientHeight
      this.camera.updateProjectionMatrix()
      this.renderer.setSize(
        this.$refs.canvasContainer.clientWidth,
        this.$refs.canvasContainer.clientHeight
      )
    },

    // 点击事件处理（选择物体）
    onClick(event) {
      // 如果正在拖动变换控制器，则不处理点击选择
      if (this.transformControls.isDragging) return

      // 计算鼠标在标准化设备坐标中的位置 (-1 到 1)
      this.mouse.x =
        (event.clientX / this.$refs.canvasContainer.clientWidth) * 2 - 1
      this.mouse.y =
        -(event.clientY / this.$refs.canvasContainer.clientHeight) * 2 + 1

      // 更新射线投射器
      this.raycaster.setFromCamera(this.mouse, this.camera)

      // 计算与射线相交的物体
      const intersects = this.raycaster.intersectObjects(
        this.scene.children,
        true
      )

      if (intersects.length > 0) {
        this.selectSceneObject(intersects[0].object)
      } else {
        this.deselectObject()
      }
    },

    // 键盘事件处理
    onKeyDown(event) {
      // 删除键删除选中对象
      if (event.key === 'Delete' && this.selectedObject) {
        this.deleteObject()
      }

      // 快捷键切换变换模式
      switch (event.key.toLowerCase()) {
        case 'w':
          this.setTransformMode('translate')
          event.preventDefault()
          break
        case 'e':
          this.setTransformMode('rotate')
          event.preventDefault()
          break
        case 'r':
          this.setTransformMode('scale')
          event.preventDefault()
          break
      }
    },

    // 选择场景对象
    selectSceneObject(object) {
      // 如果点击的是网格的一部分，选择其父对象
      var selected =
        object.parent && object.parent.isMesh ? object.parent : object

      this.selectedObject = selected
      this.transformControls.attach(selected)

      // 更新属性面板
      this.position.x = selected.position.x
      this.position.y = selected.position.y
      this.position.z = selected.position.z

      this.rotation.x = selected.rotation.x
      this.rotation.y = selected.rotation.y
      this.rotation.z = selected.rotation.z

      this.scale.x = selected.scale.x
      this.scale.y = selected.scale.y
      this.scale.z = selected.scale.z

      // 更新颜色选择器
      if (selected.material && selected.material.color) {
        this.selectedColor = '#' + selected.material.color.getHexString()
      }
    },

    // 取消选择对象
    deselectObject() {
      this.selectedObject = null
      this.transformControls.detach()
    },

    // 设置变换模式（移动/旋转/缩放）
    setTransformMode(mode) {
      this.transformControls.setMode(mode)
    },

    // 添加对象到场景
    addObject(type) {
      var object

      switch (type) {
        case 'box':
          var boxGeometry = new THREE.BoxGeometry(1, 1, 1)
          var boxMaterial = new THREE.MeshStandardMaterial({
            color: this.selectedColor
          })
          object = new THREE.Mesh(boxGeometry, boxMaterial)
          object.name = '立方体' + (this.getObjectCount('立方体') + 1)
          break

        case 'sphere':
          var sphereGeometry = new THREE.SphereGeometry(0.5, 32, 32)
          var sphereMaterial = new THREE.MeshStandardMaterial({
            color: this.selectedColor
          })
          object = new THREE.Mesh(sphereGeometry, sphereMaterial)
          object.name = '球体' + (this.getObjectCount('球体') + 1)
          break

        case 'cylinder':
          var cylinderGeometry = new THREE.CylinderGeometry(0.5, 0.5, 1, 32)
          var cylinderMaterial = new THREE.MeshStandardMaterial({
            color: this.selectedColor
          })
          object = new THREE.Mesh(cylinderGeometry, cylinderMaterial)
          object.name = '圆柱体' + (this.getObjectCount('圆柱体') + 1)
          break

        case 'plane':
          var planeGeometry = new THREE.PlaneGeometry(2, 2)
          var planeMaterial = new THREE.MeshStandardMaterial({
            color: this.selectedColor,
            side: THREE.DoubleSide
          })
          object = new THREE.Mesh(planeGeometry, planeMaterial)
          object.name = '平面' + (this.getObjectCount('平面') + 1)
          break

        case 'light':
          object = new THREE.PointLight(this.selectedColor, 1, 10)
          object.name = '点光源' + (this.getObjectCount('点光源') + 1)
          object.castShadow = true
          // 添加光源辅助线
          var lightHelper = new THREE.PointLightHelper(object, 0.5)
          lightHelper.name = object.name + '辅助线'
          object.add(lightHelper)
          break

        case 'camera':
          object = new THREE.PerspectiveCamera(75, 1, 0.1, 1000)
          object.name = '相机' + (this.getObjectCount('相机') + 1)
          object.position.z = 5
          // 添加相机辅助线
          var cameraHelper = new THREE.CameraHelper(object)
          cameraHelper.name = object.name + '辅助线'
          object.add(cameraHelper)
          break
      }

      if (object) {
        // 随机位置，避免重叠
        object.position.x = (Math.random() - 0.5) * 5
        object.position.y = (Math.random() - 0.5) * 5

        this.scene.add(object)
        this.selectSceneObject(object)
      }
    },

    // 获取特定类型对象的数量
    getObjectCount(prefix) {
      return this.scene.children.filter(function (obj) {
        return obj.name && obj.name.startsWith(prefix)
      }).length
    },

    // 改变选中对象的材质
    changeMaterial(type) {
      if (!this.selectedObject || !this.selectedObject.isMesh) return

      var material
      var color = this.selectedObject.material.color

      switch (type) {
        case 'basic':
          material = new THREE.MeshBasicMaterial({ color: color })
          break
        case 'lambert':
          material = new THREE.MeshLambertMaterial({ color: color })
          break
        case 'phong':
          material = new THREE.MeshPhongMaterial({
            color: color,
            shininess: 100
          })
          break
        case 'standard':
          material = new THREE.MeshStandardMaterial({
            color: color,
            roughness: 0.5,
            metalness: 0.5
          })
          break
      }

      if (material) {
        this.selectedObject.material.dispose() // 释放旧材质
        this.selectedObject.material = material
      }
    },

    // 改变选中对象的颜色
    changeColor() {
      if (!this.selectedObject) return

      if (this.selectedObject.isLight) {
        this.selectedObject.color.set(this.selectedColor)
      } else if (
        this.selectedObject.material &&
        this.selectedObject.material.color
      ) {
        this.selectedObject.material.color.set(this.selectedColor)
      }
    },

    // 更新位置
    updatePosition() {
      if (!this.selectedObject) return

      this.selectedObject.position.set(
        this.position.x,
        this.position.y,
        this.position.z
      )
    },

    // 更新旋转
    updateRotation() {
      if (!this.selectedObject) return

      this.selectedObject.rotation.set(
        this.rotation.x,
        this.rotation.y,
        this.rotation.z
      )
    },

    // 更新缩放
    updateScale() {
      if (!this.selectedObject) return

      this.selectedObject.scale.set(this.scale.x, this.scale.y, this.scale.z)
    },

    // 删除选中对象
    deleteObject() {
      if (!this.selectedObject) return

      // 不能删除场景本身
      if (this.selectedObject === this.scene) return

      // 移除所有子对象
      while (this.selectedObject.children.length > 0) {
        this.deleteObjectRecursive(this.selectedObject.children[0])
      }

      this.scene.remove(this.selectedObject)
      this.deselectObject()
    },

    // 递归删除对象
    deleteObjectRecursive(object) {
      while (object.children.length > 0) {
        this.deleteObjectRecursive(object.children[0])
      }

      // 释放几何体和材质
      if (object.geometry) object.geometry.dispose()
      if (object.material) {
        if (Array.isArray(object.material)) {
          object.material.forEach(function (material) {
            material.dispose()
          })
        } else {
          object.material.dispose()
        }
      }

      object.parent.remove(object)
    },

    // 新建场景
    newScene() {
      if (confirm('确定要新建场景吗？当前场景内容将丢失。')) {
        // 清除所有对象
        while (this.scene.children.length > 0) {
          this.deleteObjectRecursive(this.scene.children[0])
        }

        // 重新添加基础元素
        this.initThree()
        this.deselectObject()
      }
    },

    // 保存场景
    saveScene() {
      // 场景序列化
      var sceneData = {
        metadata: {
          version: 4.5,
          type: 'Object',
          generator: 'Three.js Editor'
        },
        objects: this.serializeObject(this.scene)
      }

      localStorage.setItem('threeEditorScene', JSON.stringify(sceneData))
      alert('场景已保存到本地存储')
    },

    // 加载场景
    loadScene() {
      var sceneData = localStorage.getItem('threeEditorScene')
      if (!sceneData) {
        alert('没有可加载的场景，请先保存')
        return
      }

      if (confirm('确定要加载保存的场景吗？当前场景内容将丢失。')) {
        // 清除当前场景
        while (this.scene.children.length > 0) {
          this.deleteObjectRecursive(this.scene.children[0])
        }

        // 解析并加载场景数据
        var data = JSON.parse(sceneData)
        this.deserializeObject(data.objects, this.scene)

        this.deselectObject()
      }
    },

    // 导出场景
    exportScene() {
      var sceneData = localStorage.getItem('threeEditorScene')
      if (!sceneData) {
        alert('没有可导出的场景，请先保存')
        return
      }

      var blob = new Blob([sceneData], { type: 'application/json' })
      var url = URL.createObjectURL(blob)
      var a = document.createElement('a')
      a.href = url
      a.download =
        'three-scene-' + new Date().toISOString().slice(0, 10) + '.json'
      document.body.appendChild(a)
      a.click()
      document.body.removeChild(a)
      URL.revokeObjectURL(url)
    },

    // 处理文件导入
    handleFileImport(event) {
      var file = event.target.files[0]
      if (!file) return

      this.importing = true
      this.importProgress = 0
      this.importFileName = file.name

      var extension = file.name.split('.').pop().toLowerCase()
      var reader = new FileReader()
      var self = this

      switch (extension) {
        case 'glb':
        case 'gltf':
          reader.onload = function (e) {
            var content = e.target.result
            self.loaders.gltf.parse(
              content,
              '',
              function (gltf) {
                self.onImportCompleted(gltf.scene, file.name)
              },
              function (error) {
                self.onImportError(error)
              }
            )
          }
          reader.readAsArrayBuffer(file)
          break

        case 'obj':
          reader.onload = function (e) {
            var content = e.target.result
            var object = self.loaders.obj.parse(content)
            self.onImportCompleted(object, file.name)
          }
          reader.readAsText(file)
          break

        case 'fbx':
          reader.onload = function (e) {
            var content = e.target.result
            var object = self.loaders.fbx.parse(content)
            self.onImportCompleted(object, file.name)
          }
          reader.readAsArrayBuffer(file)
          break

        case 'stl':
          reader.onload = function (e) {
            var geometry = self.loaders.stl.parse(e.target.result)
            var material = new THREE.MeshStandardMaterial({
              color: self.selectedColor
            })
            var mesh = new THREE.Mesh(geometry, material)
            self.onImportCompleted(mesh, file.name)
          }
          reader.readAsArrayBuffer(file)
          break

        case 'dae':
          reader.onload = function (e) {
            var content = e.target.result
            var result = self.loaders.dae.parse(content)
            self.onImportCompleted(result.scene, file.name)
          }
          reader.readAsText(file)
          break

        default:
          alert('不支持的文件格式: ' + extension)
          self.importing = false
          break
      }

      // 重置文件输入，允许重复选择同一个文件
      this.$refs.fileInput.value = ''
    },

    // 导入完成处理
    onImportCompleted(object, fileName) {
      // 设置对象名称
      object.name = fileName.split('.').slice(0, -1).join('.')

      // 居中对象
      this.centerObject(object)

      // 添加到场景
      this.scene.add(object)

      // 选择导入的对象
      this.selectSceneObject(object)

      // 完成导入
      this.importing = false
    },

    // 导入错误处理
    onImportError(error) {
      console.error('导入错误:', error)
      alert('导入失败: ' + error.message)
      this.importing = false
    },

    // 居中对象
    centerObject(object) {
      // 计算对象的边界框
      var box = new THREE.Box3().setFromObject(object)
      var center = new THREE.Vector3()
      box.getCenter(center)

      // 将对象中心移到原点
      object.position.sub(center)

      // 移到相机可见区域
      object.position.z = 0
    },

    // 序列化对象
    serializeObject(object) {
      var data = {
        uuid: object.uuid,
        name: object.name,
        type: object.type,
        position: {
          x: object.position.x,
          y: object.position.y,
          z: object.position.z
        },
        rotation: {
          x: object.rotation.x,
          y: object.rotation.y,
          z: object.rotation.z
        },
        scale: {
          x: object.scale.x,
          y: object.scale.y,
          z: object.scale.z
        }
      }

      // 序列化材质
      if (object.material && object.material.isMaterial) {
        data.material = {
          type: object.material.type,
          color: object.material.color.getHexString(),
          transparent: object.material.transparent,
          opacity: object.material.opacity
        }
      }

      // 序列化子对象
      if (object.children && object.children.length > 0) {
        data.children = object.children.map(
          function (child) {
            return this.serializeObject(child)
          }.bind(this)
        )
      }

      return data
    },

    // 反序列化对象 - 修复了语法错误的核心部分
    deserializeObject(data, parent) {
      var object

      // 根据类型创建对象
      switch (data.type) {
        case 'Scene':
          object = parent
          break

        case 'Mesh':
          // 简单处理，实际应该根据几何体类型创建
          var geometry = new THREE.BoxGeometry(1, 1, 1)
          var material = new THREE.MeshStandardMaterial({
            color: data.material
              ? '#' + data.material.color
              : this.selectedColor
          })
          object = new THREE.Mesh(geometry, material)
          break

        case 'AmbientLight':
          object = new THREE.AmbientLight(
            data.color ? parseInt(data.color, 16) : 0xffffff
          )
          break

        case 'DirectionalLight':
          object = new THREE.DirectionalLight(
            data.color ? parseInt(data.color, 16) : 0xffffff
          )
          break

        case 'PointLight':
          object = new THREE.PointLight(
            data.color ? parseInt(data.color, 16) : 0xffffff
          )
          break

        case 'PerspectiveCamera':
          object = new THREE.PerspectiveCamera(75, 1, 0.1, 1000)
          break

        default:
          object = new THREE.Object3D()
          break
      }

      // 设置基本属性
      object.name = data.name
      object.uuid = data.uuid

      if (data.position) {
        object.position.set(data.position.x, data.position.y, data.position.z)
      }

      if (data.rotation) {
        object.rotation.set(data.rotation.x, data.rotation.y, data.rotation.z)
      }

      if (data.scale) {
        object.scale.set(data.scale.x, data.scale.y, data.scale.z)
      }

      // 添加到父对象
      if (parent && object !== parent) {
        parent.add(object)
      }

      // 反序列化子对象
      if (data.children && data.children.length > 0) {
        data.children.forEach(
          function (childData) {
            this.deserializeObject(childData, object)
          }.bind(this)
        )
      }

      return object
    },

    // 获取对象图标
    getObjectIcon(obj) {
      if (obj.isScene) return 'fa-globe'
      if (obj.isCamera) return 'fa-camera'
      if (obj.isLight) return 'fa-lightbulb'
      if (obj.isMesh) {
        if (obj.geometry instanceof THREE.BoxGeometry) return 'fa-cube'
        if (obj.geometry instanceof THREE.SphereGeometry) return 'fa-circle'
        if (obj.geometry instanceof THREE.CylinderGeometry) return 'fa-cylinder'
        if (obj.geometry instanceof THREE.PlaneGeometry) return 'fa-square'
        return 'fa-cube'
      }
      return 'fa-question'
    },

    // 动画循环
    animate() {
      this.animationId = requestAnimationFrame(this.animate.bind(this))
      this.controls.update()
      this.renderer.render(this.scene, this.camera)
    }
  }
}
</script>

<style scoped>
.editor-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px;
  background-color: #333;
  color: white;
  height: 64px;
  box-sizing: border-box;
}

.logo {
  font-size: 24px;
  font-weight: bold;
}

.menu {
  display: flex;
  gap: 8px;
}

.menu-btn,
.import-btn {
  background-color: #555;
  color: white;
  border: none;
  padding: 8px 16px;
  border-radius: 4px;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
  height: 36px;
}

.menu-btn:hover,
.import-btn:hover {
  background-color: #777;
}

.editor-container {
  display: flex;
  height: calc(100vh - 64px);
}

.toolbar {
  width: 200px;
  background-color: #f5f5f5;
  padding: 16px;
  border-right: 1px solid #ddd;
  overflow-y: auto;
  box-sizing: border-box;
}

.toolbar h3 {
  margin-top: 24px;
  margin-bottom: 16px;
  font-size: 16px;
  color: #555;
  margin-left: 4px;
}

.toolbar h3:first-child {
  margin-top: 0;
}

.tool-group {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 16px;
}

.tool-btn {
  background-color: white;
  border: 1px solid #ddd;
  padding: 8px;
  border-radius: 4px;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
  height: 36px;
}

.tool-btn:hover {
  background-color: #eee;
}

.color-picker {
  margin-top: 8px;
  padding: 4px;
}

.color-picker input {
  width: 100%;
  height: 40px;
  border: none;
  cursor: pointer;
}

.editor-main {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
}
.canvas-container {
  flex: 1;
  position: relative;
  width: 100%;
}
.stats {
  padding: 16px;
  background-color: white;
  border-top: 1px solid #ddd;
  height: 200px;
  box-sizing: border-box;
  overflow-y: auto;
}
.object-controls {
  margin-top: 16px;
}
.control-group {
  margin-bottom: 16px;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
}
.control-group label {
  display: flex;
  flex-direction: column;
  font-size: 12px;
}
.control-group input {
  padding: 6px;
  border: 1px solid #ddd;
  border-radius: 3px;
  height: 28px;
  box-sizing: border-box;
}

.delete-btn {
  background-color: #ff4444;
  color: white;
  border: none;
  padding: 8px 16px;
  border-radius: 4px;
  cursor: pointer;
  margin-top: 16px;
  height: 36px;
  font-size: 14px;
}

.delete-btn:hover {
  background-color: #cc0000;
}

.object-list {
  width: 250px;
  background-color: #f5f5f5;
  padding: 16px;
  border-left: 1px solid #ddd;
  overflow-y: auto;
  box-sizing: border-box;
}

.object-list h3 {
  margin-top: 0;
  margin-bottom: 16px;
  font-size: 16px;
  color: #555;
}

.object-list ul {
  list-style: none;
  padding: 0;
  margin: 0;
}

.object-list li {
  padding: 8px;
  margin-bottom: 5px;
  background-color: white;
  border-radius: 4px;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
  height: 36px;
  box-sizing: border-box;
}

.object-list li:hover {
  background-color: #eee;
}

.object-list li.selected {
  background-color: #e3f2fd;
  border-left: 3px solid #2196f3;
}

h4 {
  margin: 0;
  font-size: 16px;
  color: #333;
}

p {
  font-size: 14px;
  color: #666;
  margin: 8px 0 0 0;
}

/* 导入进度样式 */
.import-progress {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.5);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 1000;
}

.progress-content {
  background-color: white;
  padding: 24px;
  border-radius: 8px;
  text-align: center;
}

.spinner {
  width: 40px;
  height: 40px;
  margin: 0 auto 16px;
  border: 4px solid #f3f3f3;
  border-top: 4px solid #3498db;
  border-radius: 50%;
  animation: spin 1s linear infinite;
}

@keyframes spin {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}
</style>
